package com.toy.core.security;

import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Optional;
import com.toy.core.security.exception.AuthenticationException;
import com.toy.core.security.userdetails.UserDetail;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.builder.ToStringBuilder;

public class UsernamePasswordAuthentication implements Authentication {
	
	private static final long serialVersionUID = -4291110234294190367L;
	private Object principal;
	private Object credentials;
	private boolean authenticated = false;
    private GrantedAuthority[] authorities;
	private Map<String,Object> details = new HashMap<String, Object>();
	
	public UsernamePasswordAuthentication(String username,String password) {
		this.principal = username;
		this.credentials = password;
	}
	
	 public UsernamePasswordAuthentication(String username,String password, GrantedAuthority[] authorities){
		this.principal = username;
		this.credentials = password;
		this.authorities = Optional.of(authorities).get();
		this.authenticated = true;
	 }
	 
	 public UsernamePasswordAuthentication(String username,AuthenticatedType authenticatedType){
		 if ( authenticatedType.equals(AuthenticatedType.UNKOWN) ){
			 throw new  AuthenticationException(AuthenticationException.CODE_InsufficientAuthenticationException);
		 }
		 this.principal = username;
		 this.authenticated = true;
		 setAttribute(ATTR_AUTHENTICATED_TYPE, authenticatedType);
	 }
	
	public Object getCredentials() {
		return credentials;
	}

	public Map<String,Object> getDetails() {
		return details;
	}

	public Object getPrincipal() {
		return principal;
	}

	public boolean isAuthenticated() {
		return authenticated;
	}

	public GrantedAuthority[] getAuthorities() {
        if (authorities == null) {
            return null;
        }

        GrantedAuthority[] copy = new GrantedAuthority[authorities.length];
        System.arraycopy(authorities, 0, copy, 0, authorities.length);

        return copy;
    }
	
	public String getName() {
		if (this.getPrincipal() instanceof UserDetail) {
            return ((UserDetail) this.getPrincipal()).getUsername();
        }

        return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString();
	}

	public void setAttribute(String name,Object value){
		details.put(name, value);
	}
	
	public Object getAttribute(String name){
		return details.get(name);
	}

	public void setDetails(Map<String, Object> details) {
		this.details = details;
	}

	public String toString() {
		return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
				.appendSuper(super.toString()).append("principal", principal)
				.append("authenticated", authenticated).append("authorities",
						authorities).append("details", details).toString();
	}
	
}
